package com.senseu.testserver.controller;

import com.senseu.testserver.model.Account;
import com.senseu.testserver.model.Device;
import com.senseu.testserver.repository.DeviceRepository;
import com.senseu.testserver.vo.DeviceDTO;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/device")
public class DeviceController {

    @Autowired
    private DeviceRepository deviceRepository;

    @PostMapping
    public String saveDevice(@RequestBody DeviceDTO dto) {
        List<Device> remotes = dto.getDevices();
        String node = dto.getNode();
        if (remotes == null || remotes.isEmpty()) {
            deviceRepository.updateStatusByNode(node,-1);
            return "设备为空,将所有设备置为不可用状态";
        }
        // 设置为可用
        List<Device> deviceList = deviceRepository.findDeviceByNode(node);
        List<Device> newList = new ArrayList<>();
        // 更新所有设备在线状态
        Map<String, List<Device>> remoteGroup = remotes.stream()
                .collect(Collectors.groupingBy(Device::getUdid));
        Map<String, List<Device>> grouped = deviceList.stream()
                .collect(Collectors.groupingBy(Device::getUdid));
        for (Device remote : remotes) {
            List<Device> list = grouped.get(remote.getUdid());
            if (list == null || list.isEmpty()) {
                // db中不存在，则认为是新设备
                remote.setCreateTime(Timestamp.from(Instant.now()));
                remote.setNode(node);
                newList.add(remote);
            } else {
                // 存在，则更新状态
                for (Device device : list) {
                    if (device.getStatus() != 1) {
                        device.setUpdateTime(Timestamp.from(Instant.now()));
                        if (device.getStatus() != 1) {
                            device.setStatus(0);
                        }
                    }
                }
            }
        }
        // remote 中不存在的，则将状态置为-1
        List<Device> offline = deviceList.stream().filter(new Predicate<Device>() {
            @Override
            public boolean test(Device device) {
                List<Device> devices = remoteGroup.get(device.getUdid());
                return devices == null || devices.isEmpty();
            }
        }).toList();
        for (Device device : offline) {
            device.setUpdateTime(Timestamp.from(Instant.now()));
            device.setStatus(-1);
        }
        deviceList.addAll(newList);
        deviceRepository.saveAll(deviceList);
        return "更新成功";
    }

    /**
     * 获取所有可用的设备udid列表
     */
    @GetMapping
    public List<String> getAllAvailableDevices() {
        return deviceRepository.findDevicesByStatus(0).stream().filter(new Predicate<Device>() {
            @Override
            public boolean test(Device device) {
                // 项目中约定，只支持通过tcpip连接的设备
                return device.getUdid().contains(":");
            }
        }).map(new Function<Device, String>() {
            @Override
            public String apply(Device device) {
                return device.getUdid();
            }
        }).distinct().toList();
    }

    @Transactional
    @GetMapping(value = "/allocate")
    public String allocateDevice() {
        List<Device> devices = deviceRepository.findIdleDevicesForUpdate(Pageable.ofSize(1));
        if (devices != null && !devices.isEmpty()) {
            Device device = devices.get(0);
            device.setStatus(1);
            device.setUpdateTime(Timestamp.from(Instant.now()));
            deviceRepository.save(device);
            return device.getUdid();
        }
        return "fail";
    }

    @Transactional
    @PostMapping(value = "/release")
    public String releaseDevice(@RequestParam String udid) {
        realReleaseDevice(udid);
        return "success";
    }

    public void realReleaseDevice(String udid) {
        List<Device> devices = deviceRepository.findDevicesByUdid(udid);
        if (devices != null && !devices.isEmpty()) {
            for (Device device : devices) {
                device.setUpdateTime(Timestamp.from(Instant.now()));
                if (device.getStatus() != -1) {
                    device.setStatus(0);
                }
            }
            deviceRepository.saveAll(devices);
        }
    }
}
